#pragma once

#include "SPD3D11Prerequisite.h"
#include "SPD3D11RenderEnvironment.h"
#include "SPmisc.h"

namespace SP
{
	//	class SPModule;
	//	class SPModuleDepthStencilState;
	//	class SPModuleBlendState;
	//	class SPModuleRasterizerState;
}

//----------------------------------------------------------------------------------------
// BaseClass of Module 
//----------------------------------------------------------------------------------------
namespace SP
{
	// Include "SPEmitter.h"
	class SPEmitter;

	class DLL_EXPORT SPModule
	{
	public:
		SPModule();
		virtual ~SPModule();
		virtual void Advance( float fElapsedTime );
		virtual SPModule* SpawnInstance() = 0;

		void SetEmitterOwner( SPEmitter* pOwner ){ m_pEmitter = pOwner; }
	protected:
		SPEmitter* m_pEmitter;
	};

	typedef std::list<SPModule*> SPModuleList;
}

//----------------------------------------------------------------------------------------
// General Module
//----------------------------------------------------------------------------------------
namespace SP
{
	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleDepthStencilState : public SPModule
	{
	public:
			SPModuleDepthStencilState();
			SPModuleDepthStencilState( SPModuleDepthStencilState* );
			SPModule* SpawnInstance();
			~SPModuleDepthStencilState();
		HRESULT								SetStateDesc( const D3D11_DEPTH_STENCIL_DESC& DepthStencilDesc );
		void										SetDefaultDepthStencilState();
		ID3D11DepthStencilState*		GetState(){ return m_pDepthStencilState; };
		bool IsDepthEnable(){ return m_bDepthEnable; }
	protected:
		ID3D11DepthStencilState*		m_pDepthStencilState;		
		bool m_bDepthEnable;
	};


	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleBlendState : public SPModule
	{
	public:
			SPModuleBlendState();
			SPModuleBlendState( SPModuleBlendState* );
			SPModule* SpawnInstance();
			~SPModuleBlendState();
		HRESULT								SetStateDesc( const D3D11_BLEND_DESC& BlendStateDesc );
		void										SetDefaultBlendState();
		ID3D11BlendState*				GetState(){ return m_pBlendState; }
	protected:
		ID3D11BlendState*				m_pBlendState;
	};


	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleRasterizerState : public SPModule
	{
	public:
			SPModuleRasterizerState();
			SPModuleRasterizerState( SPModuleRasterizerState* );
			SPModule* SpawnInstance();
			~SPModuleRasterizerState();
		HRESULT								SetStateDesc( const D3D11_RASTERIZER_DESC & RasterizerDesc );
		void										SetDefaultRasterizerState();
		ID3D11RasterizerState*			GetState(){ return m_pRasterizerState; }
	protected:
		ID3D11RasterizerState*			m_pRasterizerState;
	};


	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleEmitterTransform : public SPModule
	{
	public:
		SPModuleEmitterTransform();
		SPModuleEmitterTransform( SPModuleEmitterTransform* );

		void SetParm( const XMFLOAT3& vStart, const XMFLOAT3& vEnd );
		void GetParm( XMFLOAT3& vStart, XMFLOAT3& vEnd );
		virtual XMMATRIX GetTransformMatrix( float fLife ) = 0;
	protected:
		XMFLOAT3 m_vStart;
		XMFLOAT3 m_vEnd;
	};
	

	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleEmitterRotation : public SPModuleEmitterTransform
	{
	public:
		SPModuleEmitterRotation();
		SPModuleEmitterRotation( SPModuleEmitterRotation* );
		SPModule* SpawnInstance();
		XMMATRIX GetTransformMatrix( float fLife );
	};


	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleEmitterTranslation : public SPModuleEmitterTransform
	{
	public:
		SPModuleEmitterTranslation();
		SPModuleEmitterTranslation( SPModuleEmitterTranslation* );
		SPModule* SpawnInstance();
		XMMATRIX GetTransformMatrix( float fLife );
	};


	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleEmitterScale : public SPModuleEmitterTransform
	{
	public:
		SPModuleEmitterScale();
		SPModuleEmitterScale( SPModuleEmitterScale* );
		SPModule* SpawnInstance();

		XMMATRIX GetTransformMatrix( float fLife );
	};

	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleEmitterColour : public SPModule
	{
	public:
		SPModuleEmitterColour();
		SPModuleEmitterColour( SPModuleEmitterColour* );
		SPModule* SpawnInstance();

		XMVECTOR GetColour( float fLife );

		void SetParm( XMFLOAT4& start, XMFLOAT4& end )
		{
			m_vColourStart = start;
			m_vColourEnd = end;
		}

		void GetParm( XMFLOAT4& start, XMFLOAT4& end )
		{
			start = m_vColourStart;
			end = m_vColourEnd;
		}

	protected:
		XMFLOAT4 m_vColourStart;
		XMFLOAT4 m_vColourEnd;
	};

	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleEmitterCollision : public SPModule
	{
	public:
		SPModuleEmitterCollision(){}
	};
}


namespace SP // ParticleEmitter
{
	class DLL_EXPORT SPModuleParticleVector : public SPModule
	{
	public:
		virtual void Emit( UINT idx ) = 0;
		virtual void Emit( UINT idx, XMVECTOR vOrigin ) = 0;
		virtual XMVECTOR GetVector( UINT idx, float fLife ) = 0;
		virtual void AdvanceVector( UINT idx, XMVECTOR delta )= 0;
		virtual void Init() = 0;
	};

	class DLL_EXPORT SPModuleInitVector : public SPModuleParticleVector
	{
	public:
		SPModuleInitVector();
		SPModuleInitVector( SPModuleInitVector* );
		SPModule* SpawnInstance();
		~SPModuleInitVector();

		void Advance( float fElapsedTime );
		void Emit( UINT idx );
		void Emit( UINT idx, XMVECTOR vOrigin );
		XMVECTOR GetVector( UINT idx, float fLife );
		void AdvanceVector( UINT idx, XMVECTOR delta );
		void Init();
		SPRawDistributionVector* GetConstant(){ return &m_vConstant; }
	protected:
		SPRawDistributionVector m_vConstant;

		XMFLOAT3* m_pVectors;

		UINT m_nParticleCount;
	};

	class DLL_EXPORT SPModuleVectorOverLife : public SPModuleParticleVector
	{
	public:
		SPModuleVectorOverLife();
		SPModuleVectorOverLife( SPModuleVectorOverLife* );
		SPModule* SpawnInstance();
		~SPModuleVectorOverLife();

		void Advance( float fElapsedTime );
		void Emit( UINT idx );
		void Emit( UINT idx, XMVECTOR vOrigin );
		XMVECTOR GetVector( UINT idx, float fLife );
		void AdvanceVector( UINT idx, XMVECTOR delta ){}
		void Init();

		SPRawDistributionVector* GetStart(){ return &m_vStart; }
		SPRawDistributionVector* GetEnd(){ return &m_vEnd; }
	protected:
		SPRawDistributionVector m_vStart;
		SPRawDistributionVector m_vEnd;

		XMFLOAT3* m_pStartVectors;	
		XMFLOAT3* m_pEndVectors;

		UINT m_nParticleCount;
	};

	class DLL_EXPORT SPModuleInitPos : public SPModuleInitVector{};
	class DLL_EXPORT SPModulePosOverLife : public SPModuleVectorOverLife{};
	class DLL_EXPORT SPModuleInitVelo : public SPModuleInitVector{};
	class DLL_EXPORT SPModuleVeloOverLife : public SPModuleVectorOverLife{};
	class DLL_EXPORT SPModuleInitAccel : public SPModuleInitVector{};
	class DLL_EXPORT SPModuleAccelOverLife : public SPModuleVectorOverLife{};

	class DLL_EXPORT SPModuleInitColour : public SPModuleInitVector{};
	class DLL_EXPORT SPModuleColourOverLife : public SPModuleVectorOverLife{};

	class DLL_EXPORT SPModuleParticleFloat : public SPModule
	{
	public:
		virtual void Emit( UINT idx ) = 0;
		virtual FLOAT GetFloat( UINT idx, float fLife ) = 0;
		virtual void Init() = 0;
	};

	class DLL_EXPORT SPModuleInitFloat : public SPModuleParticleFloat
	{
	public:
		SPModuleInitFloat();
		SPModuleInitFloat( SPModuleInitFloat* );
		SPModule* SpawnInstance();
		~SPModuleInitFloat();

		void Advance( float fElapsedTime );
		void Emit( UINT idx );
		FLOAT GetFloat( UINT idx, float fLife );
		void Init();

		SPRawDistributionFloat* GetConstant(){ return &m_fConstant; }
	protected:
		SPRawDistributionFloat m_fConstant;
		
		FLOAT* m_pFloats;

		UINT m_nParticleCount;
	};

	class DLL_EXPORT SPModuleFloatOverLife : public SPModuleParticleFloat
	{
	public:
		SPModuleFloatOverLife();
		SPModuleFloatOverLife( SPModuleFloatOverLife* );
		SPModule* SpawnInstance();
		~SPModuleFloatOverLife();

		void Advance( float fElapsedTime );
		void Emit( UINT idx );
		FLOAT GetFloat( UINT idx, float fLife );
		void Init();

		SPRawDistributionFloat* GetStart(){ return &m_fStart; }
		SPRawDistributionFloat* GetEnd(){ return &m_fEnd; }
	protected:
		SPRawDistributionFloat m_fStart;
		SPRawDistributionFloat m_fEnd;

		FLOAT* m_pStartFloats;	
		FLOAT* m_pEndFloats;

		UINT m_nParticleCount;
	};

	class DLL_EXPORT SPModuleInitSize : public SPModuleInitFloat{};
	class DLL_EXPORT SPModuleSizeOverLife : public SPModuleFloatOverLife{};

	class DLL_EXPORT SPModuleInitAlpha : public SPModuleInitFloat{};
	class DLL_EXPORT SPModuleAlphaOverLife : public SPModuleFloatOverLife{};

	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleAttractor : public SPModule
	{
	public:

	protected:
	};

	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleOrbit : public SPModule
	{

	};


	//----------------------------------------------------------------------------------------

	//----------------------------------------------------------------------------------------

}

namespace SP // BeamEmitter
{
	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleBeamTerminal : public SPModule
	{
	public:
		SPModuleBeamTerminal();
		SPModuleBeamTerminal( SPModuleBeamTerminal* archetype );
		SPModule* SpawnInstance();

		void SetCP( XMFLOAT3& constant )
		{
			m_bCPOverLife = FALSE;
			m_vCPStart = constant;
		}

		void SetSP( XMFLOAT3& constant )
		{
			m_bSPOverLife = FALSE;
			m_vSPStart = constant;
		}

		void SetCP( XMFLOAT3& start, XMFLOAT3& end )
		{
			m_bCPOverLife = TRUE;
			m_vCPStart = start;
			m_vCPEnd = end;
		}

		void SetSP( XMFLOAT3& start, XMFLOAT3& end )
		{
			m_bSPOverLife = TRUE;
			m_vSPStart = start;
			m_vSPEnd = end;
		}

		void GetCP( XMFLOAT3& cp, FLOAT life );
		void GetSP( XMFLOAT3& sp, FLOAT life );

	protected:
		BOOL m_bCPOverLife;
		BOOL m_bSPOverLife;
		XMFLOAT3 m_vCPStart;
		XMFLOAT3 m_vCPEnd;
		XMFLOAT3 m_vSPStart;
		XMFLOAT3 m_vSPEnd;

		friend class ModuleBeamTermialBuffer;
	};

	class DLL_EXPORT SPModuleBeamTarget : public SPModuleBeamTerminal{};
	class DLL_EXPORT SPModuleBeamSource : public SPModuleBeamTerminal{};

	//----------------------------------------------------------------------------------------
	class DLL_EXPORT SPModuleBeamShape : public SPModule
	{
	public:
		SPModuleBeamShape();
		SPModuleBeamShape( SPModuleBeamShape* archetype );
		SPModule* SpawnInstance();

		void SetType( UINT t ){ m_nShapeType = t; }
		UINT GetType(){ return m_nShapeType; }


		void SetCircle( const XMFLOAT4& constant )
		{
			m_bOverLife = FALSE;
			m_vStartCenterRadius = constant;
		}

		void SetCircle( const XMFLOAT4& start, const XMFLOAT4& end )
		{
			m_bOverLife = TRUE;
			m_vStartCenterRadius = start;
			m_vEndCenterRadius = end;
		}

		void GetCircle(  XMFLOAT3& center, FLOAT& radius, FLOAT life );
	protected:		
		UINT m_nShapeType;
		BOOL m_bOverLife;
		XMFLOAT4 m_vStartCenterRadius;
		XMFLOAT4 m_vEndCenterRadius;

		friend class ModuleBeamShaperBuffer;
	};


	//----------------------------------------------------------------------------------------
}


namespace SP // AnimTrailEmitter
{
	//----------------------------------------------------------------------------------------
	
}

namespace SP // MeshEmitter
{

}

/**/